package com.houweishi.module.purchase.service.impl;

import com.alibaba.fastjson.JSON;
import com.houweishi.common.constant.Constants;
import com.houweishi.common.constant.HttpStatus;
import com.houweishi.common.core.domain.AjaxResult;
import com.houweishi.common.core.domain.entity.SysUser;
import com.houweishi.common.core.domain.model.LoginUser;
import com.houweishi.common.exception.base.BaseException;
import com.houweishi.common.utils.DateUtils;
import com.houweishi.common.utils.SecurityUtils;
import com.houweishi.module.bizSerialNum.service.IBizSerialNumTService;
import com.houweishi.module.copy.domain.BizCopy;
import com.houweishi.module.copy.mapper.BizCopyMapper;
import com.houweishi.module.leave.service.impl.OaLeaveServiceImpl;
import com.houweishi.module.purchase.domain.OaPurchase;
import com.houweishi.module.purchase.domain.OaPurchaseApproval;
import com.houweishi.module.purchase.domain.OaPurchaseProduct;
import com.houweishi.module.purchase.mapper.OaPurchaseMapper;
import com.houweishi.module.purchase.mapper.OaPurchaseProductMapper;
import com.houweishi.module.purchase.service.IOaPurchaseService;
import com.houweishi.module.record.domain.BizApprovalRecord;
import com.houweishi.module.record.mapper.BizApprovalRecordMapper;
import com.houweishi.module.record.service.IBizApprovalRecordService;
import com.houweishi.system.mapper.SysUserMapper;
import com.houweishi.ws.po.Message;
import com.houweishi.ws.service.WebSocketServer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 采购申请Service业务层处理
 * 
 * @author houweishi
 * @date 2023-03-27
 */
@Service
public class OaPurchaseServiceImpl implements IOaPurchaseService 
{
    private static final Logger LOGGER = LoggerFactory.getLogger(OaLeaveServiceImpl.class);

//    @Autowired
    @Resource
    private OaPurchaseMapper oaPurchaseMapper;

    @Resource
    private BizApprovalRecordMapper bizApprovalRecordMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private BizCopyMapper bizCopyMapper;

    @Resource
    private OaPurchaseProductMapper oaPurchaseProductMapper;

    /**
     * 生成流水单号Service
     */
    @Resource
    private IBizSerialNumTService iBizSerialNumTService;

    /**
     * 消息推送Server
     */
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 审批记录Service
     */
    @Resource
    private IBizApprovalRecordService iBizApprovalRecordService;



    /**
     * 查询采购申请
     * 
     * @param id 采购申请主键
     * @return 采购申请
     */
    @Override
    public OaPurchase selectOaPurchaseById(Long id)
    {
        OaPurchase oaPurchase = oaPurchaseMapper.selectOaPurchaseById(id);
        //根据条件查询审批记录列表
        selectApprovalRecordList(oaPurchase);
        //根据条件查询采购申请产品列表
        selectPurchaseProductList(oaPurchase);

        return oaPurchase;
    }

    /**
     * 查询采购申请列表
     * 
     * @param oaPurchase 采购申请
     * @return 采购申请
     */
    @Override
    public List<OaPurchase> selectOaPurchaseList(OaPurchase oaPurchase)
    {
        List<OaPurchase> list = oaPurchaseMapper.selectOaPurchaseList(oaPurchase);

        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(purchase -> {
                // 根据条件查询审批记录列表
                selectApprovalRecordList(purchase);
                // 根据条件查询采购申请产品列表
                selectPurchaseProductList(purchase);
            });
        }
        return list;
    }


    /**
     * 查询采购申请列表 (含业务表状态)
     * @param oaPurchase
     * @return
     */
    @Override
    public List<OaPurchaseApproval> selectOaPurchaseApprovalList(OaPurchaseApproval oaPurchase) {
        List<OaPurchaseApproval> list = oaPurchaseMapper.selectOaPurchaseApprovalList(oaPurchase);
//        if(!CollectionUtils.isEmpty(list)){
//            list.forEach(product->{
//                // 根据条件查询采购申请产品列表
//                selectPurchaseProductList(product);
//            });
//        }
        return list;
    }

    /**
     * 新增采购申请
     * 
     * @param oaPurchase 采购申请
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertOaPurchase(OaPurchase oaPurchase)
    {// 获取当前人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            return new AjaxResult(HttpStatus.UNAUTHORIZED, "请先登录");
        }
        // 判断是否再提交
        if (StringUtils.isNotBlank(oaPurchase.getSerialNum())) {
            oaPurchase.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
            oaPurchase.setUpdateBy(loginUser.getUsername());
            // 修改报销单，审批记录表，抄送
            return resubmitReimburse(oaPurchase, loginUser);
        } else {
            // 获取流水单号
            String serialNum = iBizSerialNumTService.generateSerialNum("CGSQ");
            oaPurchase.setSerialNum(serialNum);
            oaPurchase.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
            int result = oaPurchaseMapper.insertOaPurchase(oaPurchase);
            if (result < 1) {
                return new AjaxResult(HttpStatus.ERROR, "新增采购申请失败");
            }
            // 插入审批记录表
            return setApprovalRecord(oaPurchase, loginUser);
        }
    }

    /**
     * 重提交：修改报销单，审批记录表，抄送
     * @param oaPurchase
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult resubmitReimburse(OaPurchase oaPurchase,LoginUser loginUser) {
        //修改报销单
        oaPurchaseMapper.updateOaPurchase(oaPurchase);
        //删除审批记录
        bizApprovalRecordMapper.deleteBizApprovalRecordBySerialNum(oaPurchase.getSerialNum());
        // 删除抄送
        bizCopyMapper.deleteBizCopyMapperBySerialNum(oaPurchase.getSerialNum());
        //删除采购申请产品申请记录
        oaPurchaseMapper.deleteOaPurchaseProduct(oaPurchase);
        //新增审批及抄送
        return setApprovalRecord(oaPurchase,loginUser);
    }

    /**
     * 修改采购申请
     * 
     * @param oaPurchase 采购申请
     * @return 结果
     */
    @Override
    public int updateOaPurchase(OaPurchase oaPurchase)
    {
        oaPurchase.setUpdateTime(DateUtils.getNowDate());
        // 先删后增
        oaPurchaseMapper.deleteBizApprovalRecord(oaPurchase);
        oaPurchaseMapper.deleteOaPurchaseProduct(oaPurchase);
        // 插入审批记录表
        setApprovalRecord(oaPurchase, null);
        //根据条件采购申请产品列表
        selectPurchaseProductList(oaPurchase);

        return oaPurchaseMapper.updateOaPurchase(oaPurchase);
    }

    /**
     * 批量删除采购申请
     * 
     * @param ids 需要删除的采购申请主键
     * @return 结果
     */
    @Override
    public int deleteOaPurchaseByIds(Long[] ids)
    {
        return oaPurchaseMapper.deleteOaPurchaseByIds(ids);
    }

    /**
     * 删除采购申请信息
     * 
     * @param id 采购申请主键
     * @return 结果
     */
    @Override
    public int deleteOaPurchaseById(Long id)
    {
        return oaPurchaseMapper.deleteOaPurchaseById(id);
    }

    /**
     * 根据条件查询审批记录列表
     *
     * @param oaPurchase
     */
    void selectApprovalRecordList(OaPurchase oaPurchase) {
        // 三个条件定位准确的数据
        BizApprovalRecord bizApprovalRecord = new BizApprovalRecord();
        bizApprovalRecord.setApplicationId(oaPurchase.getId());
        bizApprovalRecord.setUserId(oaPurchase.getUserId());
        bizApprovalRecord.setSubscribePatternId(oaPurchase.getSubscribePatternId());

        List<BizApprovalRecord> list = bizApprovalRecordMapper.selectBizApprovalRecordList(bizApprovalRecord);
        oaPurchase.setApprovalRecordList(list);

        // 三个条件定位准确的数据（抄送）
        BizCopy bizCopy = new BizCopy();
        bizCopy.setApplicationId(oaPurchase.getId());
        bizCopy.setUserId(oaPurchase.getUserId());
        bizCopy.setSubscribePatternId(oaPurchase.getSubscribePatternId());

        List<BizCopy> list2 = bizCopyMapper.selectBizCopyList(bizCopy);
        oaPurchase.setBizCopyList(list2);
    }

    /**
     * 根据条件查询采购申请产品列表
     *
     * @param oaPurchase
     */
    void selectPurchaseProductList(OaPurchase oaPurchase) {
        OaPurchaseProduct product = new OaPurchaseProduct();
        product.setPurchaseId(oaPurchase.getId());
        List<OaPurchaseProduct> list = oaPurchaseProductMapper.selectOaPurchaseProductList(product);
        oaPurchase.setPurchaseProductList(list);
    }

    /**
     * 插入审批记录表
     *
     * @param oaPurchase
     */
    @Transactional(rollbackFor = Exception.class)
    AjaxResult setApprovalRecord(OaPurchase oaPurchase, LoginUser loginUser) {
        List<BizApprovalRecord> list;
        if ("0".equals(oaPurchase.getTypeStatus())){
            list = iBizApprovalRecordService.approvalTemplate(loginUser,oaPurchase.getSerialNum(),"采购");
        }else{
            list = addApprovalRecord(oaPurchase,loginUser);
        }
        bizApprovalRecordMapper.insertBatchBizApprovalRecord(list);

        // 增加抄送人
        addCopyPeople(oaPurchase);

        //采购申请添加产品记录
        addOaPurchaseProduct(oaPurchase);

        // 推送消息
        List<BizApprovalRecord> messageList = list.stream()
                .filter(a -> a.getSequence() == 2)
                .collect(Collectors.toList());
        sendMessage(messageList.get(0).getApproverId(), messageList.get(0).getApproverName(), oaPurchase);
        return new AjaxResult(HttpStatus.SUCCESS, "新增采购申请批记录成功");
    }

    /**
     * 自定义审批人呢
     * @param oaPurchase
     * @param loginUser
     * @return
     */
    public List<BizApprovalRecord> addApprovalRecord(OaPurchase oaPurchase, LoginUser loginUser){
        List<BizApprovalRecord> list = new ArrayList<>();
        int sequence = 1;
        // 保存发起人
        BizApprovalRecord initiatorRecord = createApprovalRecord(oaPurchase, null, loginUser);
        initiatorRecord.setSequence(sequence);
        initiatorRecord.setSerialNum(oaPurchase.getSerialNum());
        initiatorRecord.setApprovalStatus(Constants.COMPLETED);
        initiatorRecord.setTypeOperation(Constants.AGREE);
        initiatorRecord.setBusinessStatus(Constants.APPROVE);
        list.add(initiatorRecord);

        // 字符串分割，并把String[]转换为list(传入了一个字符串类型的数据）
        if (StringUtils.isEmpty(oaPurchase.getApprover())) {
            throw new BaseException("请选择采购申请审批人");
        }
        String[] approvers = oaPurchase.getApprover().split(",");
        List<Long> idList = Arrays.stream(approvers).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        // 获取详细审批人信息
        List<SysUser> sysUserList = sysUserMapper.selectUserByUserIds(idList);
        if (idList.size() != sysUserList.size()) {
            throw new BaseException("新增采购申请审批人有误");
        }
        // 根据职位级别降级排序
        sysUserList.sort(Comparator.comparingLong(SysUser::getPositionLevel).reversed());

        // 增加审批记录
        if (!CollectionUtils.isEmpty(sysUserList)) {
            for (int i = 0; i < sysUserList.size(); i++) {
                SysUser sysUser = sysUserMapper.selectUserById(sysUserList.get(i).getUserId());
                BizApprovalRecord approvalRecord = createApprovalRecord(oaPurchase, sysUser, null);
                if (i == 0) {
                    approvalRecord.setApprovalStatus(Constants.APPROVE);
                } else {
                    approvalRecord.setApprovalStatus(Constants.NOT_APPROVED);
                }
                sequence++;
                approvalRecord.setSequence(sequence);
                list.add(approvalRecord);
            }
        }
        return list;
    }

    /**
     * 添加抄送人记录
     *
     * @param oaPurchase
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void addCopyPeople(OaPurchase oaPurchase) {

        if (StringUtils.isNoneBlank(oaPurchase.getCopyerId())) {
            // 字符串分割，并把String[]转换为list，（抄送人id）
            String[] copyerIds = oaPurchase.getCopyerId().split(",");
            List<String> copyerIdList = Arrays.stream(copyerIds).collect(Collectors.toList());
            // 抄送记录表
            if (!CollectionUtils.isEmpty(copyerIdList)) {
                copyerIdList.forEach(id -> {
                    BizCopy bizCopy = new BizCopy();
                    SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(id));

                    bizCopy.setApplicationId(oaPurchase.getId());
                    bizCopy.setCopyerId(sysUser.getUserId());
                    bizCopy.setCopyerName(sysUser.getUserName());
                    bizCopy.setPositionLevel(sysUser.getPositionLevel());
                    bizCopy.setUserId(oaPurchase.getUserId());
                    bizCopy.setUsername(oaPurchase.getUsername());
                    bizCopy.setSerialNum(oaPurchase.getSerialNum());
                    bizCopy.setSubscribePatternId(oaPurchase.getSubscribePatternId());
                    bizCopy.setSubscribePatternName(oaPurchase.getSubscribePatternName());
                    bizCopy.setCopyerStatus("0");
                    bizCopy.setCreateTime(DateUtils.getNowDate());
                    bizCopyMapper.insertBizCopy(bizCopy);
                });
            }
        }

    }

    /**
     * 采购申请添加产品记录
     *
     * @param oaPurchase
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void addOaPurchaseProduct(OaPurchase oaPurchase) {
        try {
            if (!CollectionUtils.isEmpty(oaPurchase.getPurchaseProductList())) {
                oaPurchase.getPurchaseProductList().forEach(product->{
                    product.setPurchaseId(oaPurchase.getId());
                    oaPurchaseProductMapper.insertOaPurchaseProduct(product);
                });
            }
        }catch (Exception e) {
            throw new RuntimeException("采购申请添加产品失败", e);
        }
    }


    /**
     * 设置审批记录信息
     *
     * @param oaPurchase
     * @param sysUser
     * @return
     */
    public BizApprovalRecord createApprovalRecord(OaPurchase oaPurchase, SysUser sysUser, LoginUser loginUser) {
        BizApprovalRecord bizApprovalRecord = new BizApprovalRecord();
        if (null != sysUser) {
            bizApprovalRecord.setApproverId(sysUser.getUserId());
            bizApprovalRecord.setApproverName(sysUser.getUserName());
            bizApprovalRecord.setPositionLevel(sysUser.getPositionLevel());
        }
        if (null != loginUser) {
            bizApprovalRecord.setApproverId(loginUser.getUserId());
            bizApprovalRecord.setApproverName(loginUser.getUsername());
        }
        bizApprovalRecord.setSubscribePatternName("采购");
        bizApprovalRecord.setSerialNum(oaPurchase.getSerialNum());
        bizApprovalRecord.setApplicationId(oaPurchase.getId());
        bizApprovalRecord.setUserId(oaPurchase.getUserId());
        bizApprovalRecord.setUsername(oaPurchase.getUsername());
        bizApprovalRecord.setSubscribePatternId(oaPurchase.getSubscribePatternId());
        bizApprovalRecord.setSubscribePatternName(oaPurchase.getSubscribePatternName());
        bizApprovalRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        bizApprovalRecord.setUpdateBy(oaPurchase.getUsername());
        bizApprovalRecord.setCreateBy(oaPurchase.getUsername());
        bizApprovalRecord.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
        return bizApprovalRecord;
    }

    /**
     * 推送消息到前端
     *
     * @param userId
     * @param userName
     * @param oaPurchase
     */
    private void sendMessage(Long userId, String userName, OaPurchase oaPurchase) {
        try {
            // 发送消息
            Message message = new Message();
            message.setFromId(oaPurchase.getUserId());
            message.setFromName(oaPurchase.getUsername());
            message.setNextNodeId(userId);
            message.setNextNodeName(userName);
            message.setStatus(Constants.COMPLETED);
            message.setSerialNum(oaPurchase.getSerialNum());
            message.setType(oaPurchase.getSubscribePatternName());
            webSocketServer.onMessage(JSON.toJSONString(message));
        } catch (Exception e) {
            LOGGER.error("采购申请消息推送失败", e);
        }
    }

}
